package game;

import java.util.Arrays;
import java.util.Random;
import shared.util.Randomizer;

/**
 * Represents a text based Nim game board, which is simply consists 
 * of multiple sets of tokens. Each game will start with between 3 and 5 sets
 * of 1 to 7 tokens each.
 * 
 * @author Andrew
 * @author Vincent Tsuei
 * @version 11-13-2012
 */
public class GameBoard {
    
    //Specification magic numbers. Defined this way so we can easily change the
    //configuration later, if we wish.
    private static final int MIN_SETS = 3;
    private static final int MAX_SETS = 5;
    private static final int MIN_COUNT = 1;
    private static final int MAX_COUNT = 7;
    private static final int DELTA_SETS = (MAX_SETS - MIN_SETS) + 1;
    
    private volatile int sets[];
    
    public GameBoard()
    {
        resetBoard();
    }
    
    /**
     * Creates a new board with a random number of sets and items
     */
    public void resetBoard()
    {
        Random random = Randomizer.getRandom();
        sets = new int[random.nextInt(DELTA_SETS) + MIN_SETS];
        for (int i = 0; i < sets.length; i++)
        {
            sets[i] = random.nextInt(MAX_COUNT) + MIN_COUNT;
        }
    }
    
    /**
     * Attempts to update the game board with a player move. 
     * @return If the move is valid, this method will return true.
     * A false return value indicates an invalid move.
     */
    public boolean updateBoard(PlayerMove pm)
    {
        //Displayed sets start from set 1, but are stored from set 0, so subtract 1
        int s = pm.getSet() - 1;
        int n = pm.getNumberTaken();
        
        if (s >= sets.length) {
            return false;
        }
        if (n <= 0) {
            return false;
        }
        if (n > sets[s]) {
            return false;
        }
        
        sets[s] -= n;
        return true;
    }
    
    /**
     * Checks if the board is empty, indicating the game is over
     * @return True indicates the game is over, while false indicates otherwise
     */
    public boolean isBoardEmpty()
    {
        for (int i : sets)
        {
            if (i != 0)
                return false;
        }
        return true;
    }
    
    /**
     * Returns a string representation of the game board
     */
    public String getBoardString()
    {
        String s = new String();
        s += "\nset  ";
        for (int i = 0; i < sets.length; i++)
        {
           s += (i + 1) + "  ";
        }
        s += "\nsize ";
        for (int i : sets)
        {
            s += i + "  ";
        }
        s += "\n";
        
        return s;
    }
    
    /**
     * Get the number of piles.
     */
    public int getNumPiles() {
        return this.sets.length;
    }
    
    /**
     * Get the pile counts. Operations on the returned array
     * will have no effect on the game board state.
     */
    public int[] getPileCounts() {
        return Arrays.copyOf(sets, sets.length);
    }
    
}
